//还未仿真，欢迎指出问题
module handshake_fifo #(
           parameter FIFO_DATA_WIDTH = 32,
           parameter FIFO_DEPTH = 8
       )(
           input wire clk,
           input wire rst,
           input wire valid_i,
           input wire ready_i,
           input wire [31: 0] a,
           input wire [31: 0] b,
           input wire [31: 0] c,
           input wire [31: 0] d,
           input wire [31: 0] e,
           input wire [31: 0] f,
           output logic [31: 0] dout,
           output logic ready_o,
           output logic valid_o
       );
// 问题：设计一个并行6输入32比特加法器，输出1个带截断的32比特加法结果，要求用三级流水设计，带前后反压。
// 主要输入：
// 1. 6个32bit数据
// 2. 上一级的valid_i
// 3. 下一级的ready_i
// 输出：
// 1. 1个32bit结果
// 2. 给上一级的ready_o
// 3. 给下一级的valid_o
localparam WATERLINE = FIFO_DEPTH - 3; //three levels' pipeline
logic handshake;
logic handshake_ff1;
logic handshake_ff2;
logic wr_en;

assign handshake = ready_o & valid_i;

always @ (posedge clk or posedge rst)
	begin
		if (rst)
			begin
				handshake_ff1 <= '0;
				handshake_ff2 <= '0;
			end
		else
			begin
				handshake_ff1 <= handshake;
				handshake_ff2 <= handshake_ff1;
			end
	end

reg [31 : 0] r1_ab;
always @ (posedge clk or posedge rst)
	begin
		if (rst)
			begin
				r1_ab <= '0;
			end
		else if (handshake)
			begin
				r1_ab <= a + b;
			end
	end

reg [31 : 0] r1_cd;
always @ (posedge clk or posedge rst)
	begin
		if (rst)
			begin
				r1_cd <= '0;
			end
		else if (handshake)
			begin
				r1_cd <= c + d;
			end
	end

reg [31 : 0] r1_ef;
always @ (posedge clk or posedge rst)
	begin
		if (rst)
			begin
				r1_ef <= '0;
			end
		else if (handshake)
			begin
				r1_ef <= e + f;
			end
	end

reg [31 : 0] r2_abcd;
always @ (posedge clk or posedge rst)
	begin
		if (rst)
			begin
				r2_abcd <= '0;
			end
		else if (handshake_ff1)
			begin
				r2_abcd <= r1_ab + r1_cd;
			end
	end

reg [31 : 0] r2_ef;
always @ (posedge clk or posedge rst)
	begin
		if (rst)
			begin
				r2_ef <= '0;
			end
		else if (handshake_ff1)
			begin
				r2_ef <= r1_ef;
			end
	end

reg [31 : 0] r3;
always @ (posedge clk or posedge rst)
	begin
		if (rst)
			begin
				r3 <= '0;
			end
		else if (handshake_ff2)
			begin
				r3 <= r2_ef + r2_abcd;
			end
	end

always @ (posedge clk or posedge rst)
	begin
		if (rst)
			begin
				wr_en <= 1'b0;
			end
		else if (handshake_ff2)
			begin
				wr_en <= 1'b1;
			end
		else
			begin
				wr_en <= 1'b0;
			end
	end

always_ff @(posedge clk)
          begin
	          if (rst)
		          begin
			          ready_o <= 1'b0;
		          end
	          else if (usedw > WATERLINE)
		          begin
			          ready_o <= 1'b0;
		          end
	          else
		          begin
			          ready_o <= 1'b1;
		          end
          end

          assign valid_o = ~empty;
sync_fifo # (
              .MEM_TYPE ("auto" ),
              .READ_MODE ("fwft" ),
              .WIDTH (FIFO_DATA_WIDTH),
              .DEPTH (FIFO_DEPTH )
          )fifo_inst(
              .clk (clk ),  // input  wire
              .rst_n (rst_n ),  // input  wire
              .wren (wr_en ),  // input  wire
              .din (r3 ),  // input  wire [WIDTH-1:0]
              .rden (ready_i ),  // input  wire
              .dout (dout ),  // output reg  [WIDTH-1:0]
              .empty (empty ),  // output wire
              .usedw (usedw )
          );

endmodule
